﻿using System;
using System.Collections;
using SillyCube.Broadcast;
using UnityEngine;
using UnityEngine.Serialization;

namespace SillyCube.Behavior
{
    [RequireComponent(typeof(Rigidbody2D))]
    public class SampleCubeBehavior : CubeBehaviorBase
    {
        [SerializeField] private Color cubeColor = Color.white;
        [SerializeField] private Color cubeLowPowerColor = Color.white;
        private Color targetColor;
        
        [SerializeField] private int initPowerCount = 2;
        [SerializeField] private int powerCount = 1;
        [SerializeField] private GameObject breakParticlePrefab;
        
        private Rigidbody2D rigidbody2D;
        private SpriteRenderer spriteRenderer;

        private bool dead = false;

        public float forceMultiplier = 1f;

        private void Awake()
        {
            Debug.Log("Cube Awake: Hash = " + this.GetHashCode());
            
            spriteRenderer = GetComponent<SpriteRenderer>();
            rigidbody2D = GetComponent<Rigidbody2D>();

            spriteRenderer.color = cubeColor;
            targetColor = cubeColor;
        }

        private void Start()
        {
            powerCount = initPowerCount;
        }

        private void OnEnable()
        {
            BroadcastServer.Instance.ListenChannel(
                new BroadcastChannel("ComboReset"), ReceiveComboReset);
            BroadcastServer.Instance.ListenChannel(
                new BroadcastChannel("CubeDead"), ReceiveDead);
        }

        private void OnDestroy()
        {
            Debug.Log("Cube Destroyed");
            BroadcastServer.Instance.SetupListeningAllChannelsForObject(this);
        }

        private void Update()
        {
            targetColor = Color.Lerp(cubeLowPowerColor, cubeColor, (float)powerCount / initPowerCount);
            spriteRenderer.color = Color.Lerp(spriteRenderer.color, targetColor, Time.deltaTime * 3f);
        }

        private void ReceiveDead(BroadcastReceiverInfo _)
        {
            if (dead)
                return;
            
            rigidbody2D.velocity = Vector2.zero;
            rigidbody2D.isKinematic = true;
            spriteRenderer.enabled = false;
            
            var particle = Instantiate(breakParticlePrefab);
            particle.transform.position = transform.position;

            dead = true;

            StartCoroutine(CubeDeadCoroutine());
        }

        private IEnumerator CubeDeadCoroutine()
        {
            yield return new WaitForSeconds(0.5f);
            
            GameManager.Instance.GameInit();
        }

        private void ReceiveComboReset(BroadcastReceiverInfo _)
        {
            Debug.Log("Combo Reset: " + gameObject.GetHashCode());
            powerCount = initPowerCount;
        }

        public override bool AllowDragForce()
        {
            return !dead && powerCount > 0;
        }

        public override void OnForceApply(CubeBehaviorForceEventInfo info)
        {
            var rawForce = info.rawForce;
            rigidbody2D.velocity = Vector2.zero;
            rawForce = Mathf.Pow(rawForce.magnitude / 2.5f, 2) * 2.5f * rawForce.normalized; 
            rigidbody2D.AddForce(rawForce * forceMultiplier, ForceMode2D.Impulse);

            powerCount--;
        }
    }
}